package com.es.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.es.entiy.SearchParam;
import com.es.entiy.TbInvLog;
import com.es.service.ITbInvLogService;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.*;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Author SeniorTong丶
 * @Date 2021/11/19 17:33
 * @Version 1.0
 * @Remark
 */
@Service
public class TbInvLogServiceImpl implements ITbInvLogService {


    private static final Logger log = LoggerFactory.getLogger(TbInvLogServiceImpl.class);

    @Qualifier("myEsRestClient")
    @Autowired
    private RestClient restClient;

    @Qualifier("restHighLevelClient")
    @Autowired(required = false)
    private RestHighLevelClient restHighLevelClient;


    /**
     * 创建索引
     */
    @Override
    public void saveIndex(String indexName) {

        CreateIndexRequest request = new CreateIndexRequest(indexName);
        try {
            restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 校验索引是否存在
     *
     * @param indexName
     * @return
     */
    @Override
    public boolean existIndex(String indexName) {

        boolean flag = false;
        try {
            GetIndexRequest request = new GetIndexRequest(indexName);
            flag = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }


    /**
     * 添加数据
     *
     * @param invLog
     * @param indexName 索引名称
     */
    @Override
    public int saveData(TbInvLog invLog, String indexName) {

        int result = 0;
        try {
            IndexRequest request = new IndexRequest(indexName);

            request.id(invLog.getLogId().toString());
            request.source(JSON.toJSONString(invLog), XContentType.JSON);
            IndexResponse index = restHighLevelClient.index(request, RequestOptions.DEFAULT);
            System.out.println(index.toString());
            result = index.getShardInfo().getSuccessful();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ElasticsearchException ee) {
            ee.printStackTrace();
        }
        return result;
    }

    /**
     * 批量添加
     *
     * @param list
     * @param indexName
     * @return
     */
    @Override
    public boolean batchSaveData(List<TbInvLog> list, String indexName) {

        boolean flag = true;
        try {
            BulkRequest bulkRequest = new BulkRequest();

            for (TbInvLog invLog : list) {
                bulkRequest.add(new IndexRequest(indexName).id(invLog.getLogId().toString()).source(JSON.toJSONString(invLog), XContentType.JSON));
            }
            BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
            System.out.println(bulk.hasFailures());
            // bulk.hasFailures() 返回 false  表示 没有失败
            flag = bulk.hasFailures();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return flag;
    }

    /**
     * 修改数据
     *
     * @param invLog    数据
     * @param indexName 索引名称
     * @return
     */
    @Override
    public int editData(TbInvLog invLog, String indexName) {

        int result = 0;
        try {
            UpdateRequest request = new UpdateRequest(indexName, invLog.getLogId().toString());

            request.doc(JSON.toJSONString(invLog), XContentType.JSON);
            UpdateResponse update = restHighLevelClient.update(request, RequestOptions.DEFAULT);
            result = update.getShardInfo().getSuccessful();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ElasticsearchException ee) {
            ee.printStackTrace();
        }
        return result;
    }


    /**
     * 删除数据
     *
     * @param invLog
     * @param indexName
     * @return
     */
    @Override
    public int deleteData(TbInvLog invLog, String indexName) {

        int result = 0;
        try {
            DeleteRequest qyf = new DeleteRequest(indexName, invLog.getLogId().toString());
            DeleteResponse delete = restHighLevelClient.delete(qyf, RequestOptions.DEFAULT);
            System.out.println(delete.toString());
            result = delete.getShardInfo().getSuccessful();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }


    /**
     * 根据id 查单个
     *
     * @param param
     * @return
     */
    @Override
    public JSONObject getDataById(SearchParam param) {

        GetResponse documentFields = null;
        try {
            GetRequest request = new GetRequest(param.getIndex(), param.getId());
            documentFields = restHighLevelClient.get(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(documentFields.getSource());
        // 查询的 数据值
        Map<String, Object> source = documentFields.getSource();
        return new JSONObject(source);
    }


    /**
     * 查询list
     *
     * @param param
     * @return
     */
    @Override
    public JSONObject findList(SearchParam param) {
        long startTime = System.currentTimeMillis();
        Map<String, Object> map = new HashMap<>();
        try {
            //构建查询器
            SearchRequest request = new SearchRequest(param.getIndex());
            //设置查询条件
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

            //多条件查询 BoolQueryBuilder 继承  QueryBuilders
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            //范围查询   must 代表 and
            boolQueryBuilder.must(QueryBuilders.rangeQuery("OPEARATE_DATE")
                    .gte("2021-01-01").lte("2021-11-11"));

            //模糊匹配查询
//            boolQueryBuilder.must(QueryBuilders.wildcardQuery("GOODS_NAME","*车*"));
            // 多字段全部查某个值
//            boolQueryBuilder.must(QueryBuilders.queryStringQuery("全部查"));
            // 精确查询 termQuery("key", obj) 完全匹配
            // 精确查询 termsQuery("key", obj1, obj2..)   一次匹配多个值，只有有一个值是正确的，就可以查询出数据
//            boolQueryBuilder.must(QueryBuilders.termsQuery("GOODS_NAME","奔驰", "奥迪"));
            // 解析查询字符串，进行分词，然后查询
//            boolQueryBuilder.must(QueryBuilders.matchQuery("GOODS_NAME","奔驰"));


            //多条件查询放入条件中
            sourceBuilder.query(boolQueryBuilder);

            //分页, ES从第0页开始,不设置默认只会显示10条记录
            sourceBuilder.from(param.getPageNum());
            sourceBuilder.size(param.getPageSize());
            //排序
//            sourceBuilder.sort("age", SortOrder.ASC);

//            // 高亮查询  参数依次为  ->高亮前缀->高亮后缀->高亮字段
//            HighlightBuilder highlightBuilder = new HighlightBuilder();
//            highlightBuilder.preTags("<em>");
//            highlightBuilder.postTags("</em>");
//            highlightBuilder.fields().add(new HighlightBuilder.Field("GOODS_NAME"));
//            // 添加高亮查询条件到搜索源
//            sourceBuilder.highlighter(highlightBuilder);

            //将条件放入查询器
            request.source(sourceBuilder);

            //请求
            SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            SearchHit[] hits = search.getHits().getHits();

            List<TbInvLog> list = new ArrayList<>();
            for (SearchHit hit : hits) {
                TbInvLog log = new TbInvLog();
                log.setLogId(Long.valueOf(hit.getSourceAsMap().get("LOG_ID").toString()));
                log.setGoodsName(hit.getSourceAsMap().get("GOODS_NAME").toString());
                log.setGoodsNo(hit.getSourceAsMap().get("GOODS_NO").toString());
                log.setOpearateDate(hit.getSourceAsMap().get("OPEARATE_DATE").toString());
                if(hit.getSourceAsMap().get("OPT_DESC") != null){
                    log.setOptDesc(hit.getSourceAsMap().get("OPT_DESC").toString());
                } else {
                    log.setOptDesc("");
                }

                list.add(log);
            }
            map.put("list", list);
            map.put("size", list.size());
        } catch (IOException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        BigDecimal decimal = new BigDecimal(endTime - startTime).divide(new BigDecimal(1000));
        System.out.println("访问时间--------------------------------" + decimal);
        map.put("time", decimal);
        return new JSONObject(map);
    }

}
